/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  							 terrain.cpp

	$Header: /heroes4/terrain.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "terrain.h"

#include "external_string.h"

t_external_string const k_water_1_name_str( "water_1" );
t_external_string const k_water_2_name_str( "water_2" );
t_external_string const k_grass_1_name_str( "grass_1" );
t_external_string const k_grass_2_name_str( "grass_2" );
t_external_string const k_rough_1_name_str( "rough_1" );
t_external_string const k_rough_2_name_str( "rough_2" );
t_external_string const k_swamp_1_name_str( "swamp_1" );
t_external_string const k_swamp_2_name_str( "swamp_2" );
t_external_string const k_lava_1_name_str( "volcanic_1" );
t_external_string const k_lava_2_name_str( "volcanic_2" );
t_external_string const k_snow_1_name_str( "snow_1" );
t_external_string const k_snow_2_name_str( "snow_2" );
t_external_string const k_sand_1_name_str( "sand_1" );
t_external_string const k_sand_2_name_str( "sand_2" );
t_external_string const k_dirt_1_name_str( "dirt_1" );
t_external_string const k_dirt_2_name_str( "dirt_2" );
t_external_string const k_subterranean_1_name_str( "subterranean_1" );
t_external_string const k_subterranean_2_name_str( "subterranean_2" );
t_external_string const k_water_river_name_str( "water_river" );
t_external_string const k_lava_river_name_str( "lava_river" );
t_external_string const k_ice_river_name_str( "ice_river" );
t_external_string const k_magic_all_name_str( "all.special" );
t_external_string const k_magic_life_name_str( "life.special" );
t_external_string const k_magic_order_name_str( "order.special" );
t_external_string const k_magic_death_name_str( "death.special" );
t_external_string const k_magic_chaos_name_str( "chaos.special" );
t_external_string const k_magic_nature_name_str( "nature.special" );
t_external_string const k_might_name_str( "combat.special" );

t_external_string const k_water_1_description_str( "water_1.description" );
t_external_string const k_water_2_description_str( "water_2.description" );
t_external_string const k_grass_1_description_str( "grass_1.description" );
t_external_string const k_grass_2_description_str( "grass_2.description" );
t_external_string const k_rough_1_description_str( "rough_1.description" );
t_external_string const k_rough_2_description_str( "rough_2.description" );
t_external_string const k_swamp_1_description_str( "swamp_1.description" );
t_external_string const k_swamp_2_description_str( "swamp_2.description" );
t_external_string const k_lava_1_description_str( "volcanic_1.description" );
t_external_string const k_lava_2_description_str( "volcanic_2.description" );
t_external_string const k_snow_1_description_str( "snow_1.description" );
t_external_string const k_snow_2_description_str( "snow_2.description" );
t_external_string const k_sand_1_description_str( "sand_1.description" );
t_external_string const k_sand_2_description_str( "sand_2.description" );
t_external_string const k_dirt_1_description_str( "dirt_1.description" );
t_external_string const k_dirt_2_description_str( "dirt_2.description" );
t_external_string const k_subterranean_1_description_str( "subterranean_1.description" );
t_external_string const k_subterranean_2_description_str( "subterranean_2.description" );
t_external_string const k_water_river_description_str( "water_river.description" );
t_external_string const k_lava_river_description_str( "lava_river.description" );
t_external_string const k_ice_river_description_str( "ice_river.description" );
t_external_string const k_magic_all_description_str( "all.special.description" );
t_external_string const k_magic_life_description_str( "life.special.description" );
t_external_string const k_magic_order_description_str( "order.special.description" );
t_external_string const k_magic_death_description_str( "death.special.description" );
t_external_string const k_magic_chaos_description_str( "chaos.special.description" );
t_external_string const k_magic_nature_description_str( "nature.special.description" );
t_external_string const k_might_description_str( "combat.special.description" );

t_external_string const k_road_none_name_str( "road.none.terrain" );
t_external_string const k_road_1_name_str( "Road_1" );
t_external_string const k_road_2_name_str( "Road_2" );
t_external_string const k_road_3_name_str( "Road_3" );

t_external_string const k_road_none_description_str( "road.none.terrain.description" );
t_external_string const k_road_1_description_str( "Road_1.description" );
t_external_string const k_road_2_description_str( "Road_2.description" );
t_external_string const k_road_3_description_str( "Road_3.description" );

t_external_string const k_rock_terrain_none_name_str( "rock.none.terrain" );
t_external_string const k_rock_terrain_cave_name_str( "rock.cave.terrain" );
t_external_string const k_rock_terrain_stone_name_str( "rock.Stone.terrain");

t_external_string const k_rock_terrain_none_description_str( "rock.none.terrain.description" );
t_external_string const k_rock_terrain_cave_description_str( "rock.cave.terrain.description" );
t_external_string const k_rock_terrain_stone_description_str( "rock.Stone.terrain.description");


char const * const k_terrain_keyword[k_terrain_count] = 
{
	"water",
	"grass",
	"rough",
	"swamp",
	"volcanic",
	"snow",
	"sand",
	"dirt",
	"subterranean",
	"river",
	"lava",
	"ice",
	"special_all",
	"special_life",
	"special_order",
	"special_death",
	"special_chaos",
	"special_nature",
	"special_combat",
};

t_terrain_type get_terrain_type( std::string const& keyword )
{
	int i;

	for (i = 0; i < k_terrain_count; i++)
	{
		if (stricmp( keyword.c_str(), k_terrain_keyword[i] ) == 0)
			return t_terrain_type(i);
	}
	return k_terrain_count;
}

// ------------------------------------------------------------------------------
// Unnamed namespace
// ------------------------------------------------------------------------------

namespace
{

	// ------------------------------------------------------------------------------
	// t_terrain_type_properties_base struct
	// ------------------------------------------------------------------------------
	
	struct t_terrain_type_properties_base
	{
	public:
		// Data members
		t_external_string const &		name;
		t_external_string const &		description;

		// Constructor
		t_terrain_type_properties_base( t_external_string const & name_arg, t_external_string const & description_arg );
	};

	inline t_terrain_type_properties_base::t_terrain_type_properties_base(
		t_external_string const & name_arg, t_external_string const & description_arg )
		:	name( name_arg ),
			description( description_arg )
	{
	}

	// ------------------------------------------------------------------------------
	// t_terrain_subtype_properties struct
	// ------------------------------------------------------------------------------

	typedef t_terrain_type_properties_base t_terrain_subtype_properties;

	// ------------------------------------------------------------------------------
	// t_terrain_type_properties struct
	// ------------------------------------------------------------------------------

	struct t_terrain_type_properties
	{
	public:
		// Data members
		t_terrain_type							basic_type;
		t_terrain_subtype_properties const *	subtype_properties_array;

		// Constructor
		t_terrain_type_properties(
			t_terrain_type							basic_type_arg,
			t_terrain_subtype_properties const *	subtype_properties_array_Arg );
	};

	inline t_terrain_type_properties::t_terrain_type_properties(
		t_terrain_type							basic_type_arg,
		t_terrain_subtype_properties const *	subtype_properties_array_arg )
		:	basic_type( basic_type_arg ),
			subtype_properties_array( subtype_properties_array_arg )
	{
	}

	typedef t_terrain_type_properties t_terrain_type_properties_array[ k_terrain_count ];

	// ------------------------------------------------------------------------------
	// ------------------------------------------------------------------------------
	t_terrain_type_properties_array const & get_terrain_type_properties_array()
	{
		static t_terrain_subtype_properties const k_water_subtype_properties_array[ k_terrain_water_subtype_count ] =
		{
			t_terrain_subtype_properties( k_water_1_name_str, k_water_1_description_str ),
			t_terrain_subtype_properties( k_water_2_name_str, k_water_2_description_str ),
		};

		static t_terrain_subtype_properties const k_grass_subtype_properties_array[ k_terrain_grass_subtype_count ] =
		{
			t_terrain_subtype_properties( k_grass_1_name_str, k_grass_1_description_str ),
			t_terrain_subtype_properties( k_grass_2_name_str, k_grass_2_description_str ),
		};

		static t_terrain_subtype_properties const k_rough_subtype_properties_array[ k_terrain_rough_subtype_count ] =
		{
			t_terrain_subtype_properties( k_rough_1_name_str, k_rough_1_description_str ),
			t_terrain_subtype_properties( k_rough_2_name_str, k_rough_2_description_str ),
		};

		static t_terrain_subtype_properties const k_swamp_subtype_properties_array[ k_terrain_swamp_subtype_count ] =
		{
			t_terrain_subtype_properties( k_swamp_1_name_str, k_swamp_1_description_str ),
			t_terrain_subtype_properties( k_swamp_2_name_str, k_swamp_2_description_str ),
		};

		static t_terrain_subtype_properties const k_lava_subtype_properties_array[ k_terrain_lava_subtype_count ] =
		{
			t_terrain_subtype_properties( k_lava_1_name_str, k_lava_1_description_str ),
			t_terrain_subtype_properties( k_lava_2_name_str, k_lava_2_description_str ),
		};

		static t_terrain_subtype_properties const k_snow_subtype_properties_array[ k_terrain_snow_subtype_count ] =
		{
			t_terrain_subtype_properties( k_snow_1_name_str, k_snow_1_description_str ),
			t_terrain_subtype_properties( k_snow_2_name_str, k_snow_2_description_str ),
		};

		static t_terrain_subtype_properties const k_sand_subtype_properties_array[ k_terrain_sand_subtype_count ] =
		{
			t_terrain_subtype_properties( k_sand_1_name_str, k_sand_1_description_str ),
			t_terrain_subtype_properties( k_sand_2_name_str, k_sand_2_description_str ),
		};

		static t_terrain_subtype_properties const k_dirt_subtype_properties_array[ k_terrain_dirt_subtype_count ] =
		{
			t_terrain_subtype_properties( k_dirt_1_name_str, k_dirt_1_description_str ),
			t_terrain_subtype_properties( k_dirt_2_name_str, k_dirt_2_description_str ),
		};

		static t_terrain_subtype_properties const k_subterranean_subtype_properties_array[ k_terrain_subterranean_subtype_count ] =
		{
			t_terrain_subtype_properties( k_subterranean_1_name_str, k_subterranean_1_description_str ),
			t_terrain_subtype_properties( k_subterranean_2_name_str, k_subterranean_2_description_str ),
		};

		static t_terrain_subtype_properties const k_water_river_subtype_properties_array[ k_terrain_water_river_subtype_count ] =
		{
			t_terrain_subtype_properties( k_water_river_name_str, k_water_river_description_str ),
		};

		static t_terrain_subtype_properties const k_lava_river_subtype_properties_array[ k_terrain_lava_river_subtype_count ] =
		{
			t_terrain_subtype_properties( k_lava_river_name_str, k_lava_river_description_str ),
		};

		static t_terrain_subtype_properties const k_ice_river_subtype_properties_array[ k_terrain_ice_river_subtype_count ] =
		{
			t_terrain_subtype_properties( k_ice_river_name_str, k_ice_river_description_str ),
		};

		static t_terrain_subtype_properties const k_magic_all_subtype_properties_array[ k_terrain_magic_all_subtype_count ] =
		{
			t_terrain_subtype_properties( k_magic_all_name_str, k_magic_all_description_str ),
		};

		static t_terrain_subtype_properties const k_magic_life_subtype_properties_array[ k_terrain_magic_life_subtype_count ] =
		{
			t_terrain_subtype_properties( k_magic_life_name_str, k_magic_life_description_str ),
		};

		static t_terrain_subtype_properties const k_magic_order_subtype_properties_array[ k_terrain_magic_order_subtype_count ] =
		{
			t_terrain_subtype_properties( k_magic_order_name_str, k_magic_order_description_str ),
		};

		static t_terrain_subtype_properties const k_magic_death_subtype_properties_array[ k_terrain_magic_death_subtype_count ] =
		{
			t_terrain_subtype_properties( k_magic_death_name_str, k_magic_death_description_str ),
		};

		static t_terrain_subtype_properties const k_magic_chaos_subtype_properties_array[ k_terrain_magic_chaos_subtype_count ] =
		{
			t_terrain_subtype_properties( k_magic_chaos_name_str, k_magic_chaos_description_str ),
		};

		static t_terrain_subtype_properties const k_magic_nature_subtype_properties_array[ k_terrain_magic_nature_subtype_count ] =
		{
			t_terrain_subtype_properties( k_magic_nature_name_str, k_magic_nature_description_str ),
		};

		static t_terrain_subtype_properties const k_might_subtype_properties_array[ k_terrain_might_subtype_count ] =
		{
			t_terrain_subtype_properties( k_might_name_str, k_might_description_str ),
		};

		static t_terrain_type_properties const k_terrain_type_properties_array[ k_terrain_count ] =
		{
			t_terrain_type_properties( k_terrain_water,			k_water_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_grass,			k_grass_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_rough,			k_rough_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_swamp,			k_swamp_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_lava,			k_lava_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_snow,			k_snow_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_sand,			k_sand_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_dirt,			k_dirt_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_subterranean,	k_subterranean_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_water,			k_water_river_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_lava,			k_lava_river_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_snow,			k_ice_river_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_grass,			k_magic_all_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_grass,			k_magic_life_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_grass,			k_magic_order_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_lava,			k_magic_death_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_lava,			k_magic_chaos_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_grass,			k_magic_nature_subtype_properties_array ),
			t_terrain_type_properties( k_terrain_grass,			k_might_subtype_properties_array ),
		};

		return k_terrain_type_properties_array;
	}

	// ------------------------------------------------------------------------------
	// ------------------------------------------------------------------------------
	inline t_terrain_type_properties const & get_terrain_type_properties( t_terrain_type type )
	{
		assert( type >= 0 && type < k_terrain_count );

		static t_terrain_type_properties_array const & k_properties_array = get_terrain_type_properties_array();

		return k_properties_array[ type ];
	}

	// ------------------------------------------------------------------------------
	// t_road_type_properties struct
	// ------------------------------------------------------------------------------

	typedef t_terrain_type_properties_base t_road_type_properties;

	// ------------------------------------------------------------------------------
	// ------------------------------------------------------------------------------
	inline t_road_type_properties const & get_road_type_properties( t_road_type type )
	{
		assert( type >= 0 && type < k_road_type_count );

		static t_road_type_properties const k_properties_array[ k_road_type_count ] =
		{
			t_road_type_properties(	k_road_none_name_str, k_road_none_description_str ),
			t_road_type_properties( k_road_1_name_str, k_road_1_description_str ),
			t_road_type_properties( k_road_2_name_str, k_road_2_description_str ),
			t_road_type_properties( k_road_3_name_str, k_road_3_description_str ),
		};

		return k_properties_array[ type ];
	}

	// ------------------------------------------------------------------------------
	// t_rock_terrain_type_properties struct
	// ------------------------------------------------------------------------------

	typedef t_terrain_type_properties_base t_rock_terrain_type_properties;

	// ------------------------------------------------------------------------------
	// ------------------------------------------------------------------------------
	inline t_rock_terrain_type_properties const &
	get_rock_terrain_type_properties( t_rock_terrain_type type )
	{
		assert( type >= 0 && type < k_rock_terrain_type_count );

		static t_rock_terrain_type_properties const k_properties_array[ k_rock_terrain_type_count ] =
		{
			t_rock_terrain_type_properties( k_rock_terrain_none_name_str, k_rock_terrain_none_description_str ),
			t_rock_terrain_type_properties( k_rock_terrain_cave_name_str, k_rock_terrain_cave_description_str ),
			t_rock_terrain_type_properties( k_rock_terrain_stone_name_str, k_rock_terrain_stone_description_str ),
		};

		return k_properties_array[ type ];
	}

} // Unnamed namespace

t_terrain_type get_basic_terrain( t_terrain_type type )
{
	return get_terrain_type_properties( type ).basic_type;
};

std::string const & get_terrain_type_name( t_terrain_type type, int subtype )
{
	assert( type >= 0 && type < k_terrain_count );
	assert( subtype >= 0 && subtype < get_terrain_subtype_count( type ) );

	return get_terrain_type_properties( type ).subtype_properties_array[ subtype ].name;
}

std::string const & get_terrain_type_description( t_terrain_type type, int subtype )
{
	assert( type >= 0 && type < k_terrain_count );
	assert( subtype >= 0 && subtype < get_terrain_subtype_count( type ) );

	return get_terrain_type_properties( type ).subtype_properties_array[ subtype ].description;
}

std::string const & get_road_type_name( t_road_type type )
{
	return get_road_type_properties( type ).name;
}

std::string const & get_road_type_description( t_road_type type )
{
	return get_road_type_properties( type ).description;
}

std::string const & get_rock_terrain_type_name( t_rock_terrain_type type )
{
	return get_rock_terrain_type_properties( type ).name;
}

std::string const & get_rock_terrain_type_description( t_rock_terrain_type type )
{
	return get_rock_terrain_type_properties( type ).description;
}
